﻿#region Creditos

/* Autor: Edilberto Sánchez Forero	*/
/* Email: esanchezfo@gmail.com		*/
/* Licencia: LGPL, Software Libre	*/
/* País: Colombia, Bogotá			*/

#endregion

#region Librerias

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

using ESF.Object.XmlRepresenter;
using ESF.General;
using ESF.General.Text;

#endregion


namespace ESF.Object.SolutionGenerator.Services.Core
{
	public static class ControllerGenerator
	{
		#region Funciones para generar controladores
		
		internal static void GenerateClass (TextWriter ptxtWriter, string pstrBaseNamespace, string pstrBaseClassName, XmlObject pobjObject)
		{
			XmlObject objRefObj;
			XmlObject objExtRefObj;
			
		
			#region Usings
			
			ptxtWriter.WriteLine ("#region Libraries");
			ptxtWriter.WriteLine ();
			ptxtWriter.WriteLine ("using System;");
			ptxtWriter.WriteLine ("using System.Xml;");
			ptxtWriter.WriteLine ("using System.Collections.Generic;");
			ptxtWriter.WriteLine ("using System.Data;");
			ptxtWriter.WriteLine ();
			ptxtWriter.WriteLine ("using ESF.General;");
			ptxtWriter.WriteLine ();
			
			SolGenerator.AddEntitiesUsings (ref ptxtWriter, pobjObject.Members);
			SolGenerator.AddControllersUsings (ref ptxtWriter, pobjObject.Members);
			
			ptxtWriter.WriteLine ("using {0}.{1}.Entities;", pstrBaseNamespace, pobjObject.SetName);
			ptxtWriter.WriteLine ("using {0}.{1}.DataAccesses;", pstrBaseNamespace, pobjObject.SetName);
			ptxtWriter.WriteLine ();
			ptxtWriter.WriteLine ("#endregion");	
			ptxtWriter.WriteLine ();
			ptxtWriter.WriteLine ();
			
			#endregion
				
			ptxtWriter.Write ("namespace {0}.{1}.Controllers", pstrBaseNamespace, pobjObject.SetName);
			ptxtWriter.Write (TextHelper.NL_CO);
			ptxtWriter.Write ("public class {0}{1}", pstrBaseClassName, pobjObject.Name);
			ptxtWriter.Write (TextHelper.NL_1_TAB_CO);
			
			#region Funciones de Lectura
			
			ptxtWriter.Write (TextHelper.NL_2_TAB);
			ptxtWriter.WriteLine ("#region Read Only Functions");
		
			foreach (XmlMember objMember in pobjObject.CustomMembers)
			{
				objRefObj = SolGenerator.ObjectSetManager.GetObjectBy (objMember);
			
				if (objRefObj.IsArray)
				{
					objExtRefObj = SolGenerator.ObjectSetManager [objRefObj.SetName][objRefObj.Type];
					
					ControllerGenerator.GenerateSelectRefArrayByMe (ref ptxtWriter, pobjObject, objMember, objExtRefObj);
				
					ControllerGenerator.GenerateSelectArraySelfByRef (ref ptxtWriter, pobjObject, objMember, objExtRefObj);
				}
			}
		
			ControllerGenerator.GenerateSelect (ref ptxtWriter, pobjObject);
			
			if (pobjObject.HasEnabledMember)
			{
				ControllerGenerator.GenerateSelectEnabled (ref ptxtWriter, pobjObject);
			}
		
			ControllerGenerator.GenerateSelectByID (ref ptxtWriter, pobjObject);
			ControllerGenerator.GenerateCount (ref ptxtWriter, pobjObject);
		
			if (pobjObject.HasNameMember)
			{
				ControllerGenerator.GenerateSelectList (ref ptxtWriter, pobjObject);
				
				if (pobjObject.HasEnabledMember)
				{
					ControllerGenerator.GenerateSelectEnabledList (ref ptxtWriter, pobjObject);
				}
			}
			
			ptxtWriter.Write (TextHelper.NL_2_TAB);
			ptxtWriter.WriteLine ("#endregion");
			
			#endregion
						
			#region Funciones de Edicion
			
			ptxtWriter.WriteLine ();
			ptxtWriter.Write (TextHelper.NL_2_TAB);
			ptxtWriter.WriteLine ("#region Edit Functions");
			
			foreach (XmlMember objMember in pobjObject.CustomMembers)
			{
				objRefObj = SolGenerator.ObjectSetManager.GetObjectBy (objMember);
			
				if (objRefObj.IsArray)
				{
					objExtRefObj = SolGenerator.ObjectSetManager [objRefObj.SetName][objRefObj.Type];
					
					ControllerGenerator.GenerateDeleteArrayByRef (ref ptxtWriter, pobjObject, objMember, objExtRefObj);
					ControllerGenerator.GenerateDeleteArrayBySelf (ref ptxtWriter, pobjObject, objMember, objExtRefObj);
					
					ControllerGenerator.GenerateInsertArray (ref ptxtWriter, pobjObject, objMember, objExtRefObj);
				}
			}
		
			ControllerGenerator.GenerateDelete (ref ptxtWriter, pobjObject);
			ControllerGenerator.GenerateInsertUpdate (ref ptxtWriter, pobjObject);
			
			ptxtWriter.Write (TextHelper.NL_2_TAB);
			ptxtWriter.WriteLine ("#endregion");
			ptxtWriter.WriteLine ();
			
			#endregion			
			
			ptxtWriter.Write (TextHelper.NL_1_TAB_CC);
			ptxtWriter.Write (TextHelper.NL_CC);
			ptxtWriter.Close ();
		}
		
		#endregion
		
		
		#region Funciones para Lectura
		
		private static void GenerateSelectArraySelfByRef (ref TextWriter ptxtWriter, XmlObject pobjObject, XmlMember pobjMember, XmlObject pobjExtRefObject)
		{
			ptxtWriter.Write (TextHelper.NL_2_TAB);
			ptxtWriter.Write ("public static List<{0}> SelectSelfArrayOf_{0}_By_{1} ({2} pobjRI)", pobjObject.Name, pobjMember.Name, pobjExtRefObject.Name);
			ptxtWriter.Write (TextHelper.NL_2_TAB_CO);
			
			ptxtWriter.Write ("{0}.Validator.FilledID (pobjRI.ID);", pobjExtRefObject.Name);
			
			ptxtWriter.Write (TextHelper.NL_3_TAB);
			ptxtWriter.Write ("return BaseAdo{0}.SelectSelfArrayOf_{0}_By_{1} (pobjRI);", pobjObject.Name, pobjMember.Name);
			
			ptxtWriter.WriteLine (TextHelper.NL_2_TAB_CC);
		}
		
		
		private static void GenerateSelectRefArrayByMe (ref TextWriter ptxtWriter, XmlObject pobjObject, XmlMember pobjMember, XmlObject pobjExtRefObject)
		{
			ptxtWriter.Write (TextHelper.NL_2_TAB);
			ptxtWriter.Write ("public static List<{0}> SelectRefArrayOf_{1}_By_{2} ({2} pobjI)", pobjExtRefObject.Name, pobjMember.Name, pobjObject.Name);
			ptxtWriter.Write (TextHelper.NL_2_TAB_CO);
			
			ptxtWriter.Write ("{0}.Validator.FilledID (pobjI.ID);", pobjObject.Name);
			
			ptxtWriter.Write (TextHelper.NL_3_TAB);
			ptxtWriter.Write ("return BaseAdo{1}.SelectRefArrayOf_{0}_By_{1} (pobjI);", pobjMember.Name, pobjObject.Name);
			
			ptxtWriter.WriteLine (TextHelper.NL_2_TAB_CC);
		}
		
		
		private static void GenerateSelect (ref TextWriter ptxtWriter, XmlObject pobjObject)
		{
			ptxtWriter.Write (TextHelper.NL_2_TAB);
			ptxtWriter.Write ("public static void SelectFirst (ref {0} pobjI)", pobjObject.Name);
			ptxtWriter.Write (TextHelper.NL_2_TAB_CO);
			ptxtWriter.WriteLine ("PaggingInfo objPagInfo;");
			ptxtWriter.Write (TextHelper.NL_3_TAB);
			ptxtWriter.WriteLine ("List<{0}> lstObj;", pobjObject.Name);
			ptxtWriter.Write (TextHelper.NL_3_TAB);
			ptxtWriter.WriteLine ("objPagInfo = new PaggingInfo ();");
			ptxtWriter.Write (TextHelper.NL_3_TAB);
			ptxtWriter.WriteLine ("lstObj = BaseCtrl{0}.Select (pobjI, ref objPagInfo);", pobjObject.Name);
			ptxtWriter.Write (TextHelper.NL_3_TAB);
			ptxtWriter.Write ("if (lstObj == null || lstObj.Count == 0)");
			ptxtWriter.Write (TextHelper.NL_3_TAB_CO);
			ptxtWriter.Write ("pobjI = null;");
			ptxtWriter.Write (TextHelper.NL_3_TAB_CC);
			ptxtWriter.Write (TextHelper.NL_3_TAB);
			ptxtWriter.Write ("pobjI = lstObj [0];");
			ptxtWriter.WriteLine (TextHelper.NL_2_TAB_CC);
		
		
			ptxtWriter.Write (TextHelper.NL_2_TAB);
			ptxtWriter.Write ("public static List<{0}> Select ({0} pobjI, ref PaggingInfo pobjPagInfo)", pobjObject.Name);
			ptxtWriter.Write (TextHelper.NL_2_TAB_CO);
			ptxtWriter.Write ("return BaseAdo{0}.Select (pobjI, ref pobjPagInfo);", pobjObject.Name);
			ptxtWriter.WriteLine (TextHelper.NL_2_TAB_CC);
		}
		
		
		private static void GenerateSelectEnabled (ref TextWriter ptxtWriter, XmlObject pobjObject)
		{
			ptxtWriter.Write (TextHelper.NL_2_TAB);
			ptxtWriter.Write ("public static void SelectFirstEnabled (ref {0} pobjI)", pobjObject.Name);
			ptxtWriter.Write (TextHelper.NL_2_TAB_CO);
			ptxtWriter.WriteLine ("PaggingInfo objPagInfo;");
			ptxtWriter.Write (TextHelper.NL_3_TAB);
			ptxtWriter.WriteLine ("List<{0}> lstObj;", pobjObject.Name);
			ptxtWriter.Write (TextHelper.NL_3_TAB);
			ptxtWriter.WriteLine ("objPagInfo = new PaggingInfo ();");
			ptxtWriter.Write (TextHelper.NL_3_TAB);
			ptxtWriter.WriteLine ("lstObj = BaseCtrl{0}.SelectEnabled (pobjI, ref objPagInfo);", pobjObject.Name);
			ptxtWriter.Write (TextHelper.NL_3_TAB);
			ptxtWriter.Write ("if (lstObj == null || lstObj.Count == 0)");
			ptxtWriter.Write (TextHelper.NL_3_TAB_CO);
			ptxtWriter.Write ("pobjI = null;");
			ptxtWriter.Write (TextHelper.NL_3_TAB_CC);
			ptxtWriter.Write (TextHelper.NL_3_TAB);
			ptxtWriter.Write ("pobjI = lstObj [0];");
			ptxtWriter.WriteLine (TextHelper.NL_2_TAB_CC);
			
		
			ptxtWriter.Write (TextHelper.NL_2_TAB);
			ptxtWriter.Write ("public static List<{0}> SelectEnabled ({0} pobjI, ref PaggingInfo pobjPagInfo)", pobjObject.Name);
			ptxtWriter.Write (TextHelper.NL_2_TAB_CO);
			ptxtWriter.Write ("pobjI.Enabled = true;");
			ptxtWriter.Write (TextHelper.NL_3_TAB);
			ptxtWriter.Write ("pobjI.UseFilter_{0} = true;", pobjObject.EnabledMember.Name);
			ptxtWriter.Write (TextHelper.NL_3_TAB);
			ptxtWriter.Write ("return BaseAdo{0}.Select (pobjI, ref pobjPagInfo);", pobjObject.Name);
			ptxtWriter.WriteLine (TextHelper.NL_2_TAB_CC);
		}
		
		
		private static void GenerateSelectByID (ref TextWriter ptxtWriter, XmlObject pobjObject)
		{
			ptxtWriter.Write (TextHelper.NL_2_TAB);
			ptxtWriter.Write ("public static void SelectByID (ref {0} pobjI)", pobjObject.Name);
			ptxtWriter.Write (TextHelper.NL_2_TAB_CO);			
			ptxtWriter.Write ("{0}.Validator.FilledID (pobjI.ID);", pobjObject.Name);
			ptxtWriter.Write (TextHelper.NL_3_TAB);
			ptxtWriter.Write ("pobjI.UseFilter_ID = true;");
			ptxtWriter.Write (TextHelper.NL_3_TAB);
			ptxtWriter.Write ("BaseCtrl{0}.SelectFirst (ref pobjI);", pobjObject.Name);
			ptxtWriter.WriteLine (TextHelper.NL_2_TAB_CC);
		}
		
		
		private static void GenerateCount (ref TextWriter ptxtWriter, XmlObject pobjObject)
		{
			ptxtWriter.Write (TextHelper.NL_2_TAB);
			ptxtWriter.Write ("public static ulong? Count ()", pobjObject.Name);
			ptxtWriter.Write (TextHelper.NL_2_TAB_CO);
			ptxtWriter.Write ("return BaseCtrl{0}.Count (null);", pobjObject.Name);
			ptxtWriter.WriteLine (TextHelper.NL_2_TAB_CC);
		
			ptxtWriter.Write (TextHelper.NL_2_TAB);
			ptxtWriter.Write ("public static ulong? Count ({0} pobjI)", pobjObject.Name);
			ptxtWriter.Write (TextHelper.NL_2_TAB_CO);			
			ptxtWriter.Write ("return BaseAdo{0}.Count (pobjI);", pobjObject.Name);
			ptxtWriter.WriteLine (TextHelper.NL_2_TAB_CC);
		}
		
		
		private static void GenerateSelectList (ref TextWriter ptxtWriter, XmlObject pobjObject)
		{
			ptxtWriter.Write (TextHelper.NL_2_TAB);
			ptxtWriter.Write ("public static List<{0}> SelectList ()", pobjObject.Name);
			ptxtWriter.Write (TextHelper.NL_2_TAB_CO);
			
			ptxtWriter.Write ("return BaseAdo{0}.SelectList ();", pobjObject.Name);
			
			ptxtWriter.WriteLine (TextHelper.NL_2_TAB_CC);
		}
		
		
		private static void GenerateSelectEnabledList (ref TextWriter ptxtWriter, XmlObject pobjObject)
		{
			ptxtWriter.Write (TextHelper.NL_2_TAB);
			ptxtWriter.Write ("public static List<{0}> SelectEnabledList ()", pobjObject.Name);
			ptxtWriter.Write (TextHelper.NL_2_TAB_CO);
			
			ptxtWriter.Write ("return BaseAdo{0}.SelectEnabledList ();", pobjObject.Name);
			
			ptxtWriter.WriteLine (TextHelper.NL_2_TAB_CC);
		}
		
		#endregion
		
		
		#region Funciones para Edicion
		
		private static void GenerateDelete (ref TextWriter ptxtWriter, XmlObject pobjObject)
		{
			ptxtWriter.Write (TextHelper.NL_2_TAB);
			ptxtWriter.Write ("public static void Delete ({0} pobjI)", pobjObject.Name);
			ptxtWriter.Write (TextHelper.NL_2_TAB_CO);
			
			ptxtWriter.Write ("{0}.Validator.FilledID (pobjI.ID);", pobjObject.Name);
			
			ptxtWriter.Write (TextHelper.NL_3_TAB);
			ptxtWriter.Write ("BaseAdo{0}.DeleteByID (pobjI);", pobjObject.Name);
			
			ptxtWriter.WriteLine (TextHelper.NL_2_TAB_CC);
		}
		
		
		private static void GenerateInsertUpdate (ref TextWriter ptxtWriter, XmlObject pobjObject)
		{
			XmlObject objRefObject;
			
		
			ptxtWriter.Write (TextHelper.NL_2_TAB);
			ptxtWriter.Write ("public static void InsertUpdate (ref {0} pobjI)", pobjObject.Name);
			ptxtWriter.Write (TextHelper.NL_2_TAB_CO);
			
			ptxtWriter.WriteLine ("Validate objVal;");
			ptxtWriter.WriteLine ();
			
			ptxtWriter.Write (TextHelper.NL_3_TAB);
			ptxtWriter.WriteLine ("objVal = new Validate ();");
			ptxtWriter.WriteLine ();
			
			#region NoCustomMembers
			
			foreach (XmlMember objMember in pobjObject.NoCustomMembers)
			{
				ptxtWriter.Write (TextHelper.NL_3_TAB);
				ptxtWriter.WriteLine ("objVal.FilledObject ({1}, \"{0}\", pobjI.{0});", 
					objMember.Name, objMember.Required.ToString ().ToLower ());
				
				switch (objMember.Type)
				{
					case ValueTypes.String:
						
						ptxtWriter.Write (TextHelper.NL_3_TAB);
						ptxtWriter.Write ("objVal.Filled ({1}, \"{0}\", pobjI.{0}", 
							objMember.Name, objMember.Required.ToString ().ToLower ());
						
						if (objMember.MinLength != null)
						{
							ptxtWriter.Write (", {0}", objMember.MinLength.Value);
						}
						else
						{
							ptxtWriter.Write (", 0");
						}
						
						if (objMember.ApplicableMaxLength != null)
						{
							ptxtWriter.Write (", {0}", objMember.ApplicableMaxLength.Value);
						}
						else
						{
							ptxtWriter.Write (", 0");
						}
						
						if (objMember.RegEx != null)
						{
							ptxtWriter.Write (", @\"{0}\"", objMember.RegEx.ToString ());
						}
						
						ptxtWriter.WriteLine (");");
						
						break;
						
					case ValueTypes.DateTime: goto case ValueTypes.Date;
					
					case ValueTypes.Date: 
					
						// TODO: Aplicar el xmlmember con min y max values
						break;
						
					// TODO: Aplicar mas validacoines por otros tipos (numeric, min max values)
				}
			}
			
			#endregion
		
			#region Custom Members
		
			foreach (XmlMember objMember in pobjObject.CustomMembers)
			{
				objRefObject = SolGenerator.ObjectSetManager.GetObjectBy (objMember);
				
				if (!objRefObject.IsArray)
				{
					ptxtWriter.Write (TextHelper.NL_3_TAB);
					ptxtWriter.Write ("objVal.FilledObject ({1}, \"{0}\", pobjI.{0});", 
						objMember.Name, objMember.Required.ToString ().ToLower ());
				}
			}
			
			#endregion
			
			ptxtWriter.Write (TextHelper.NL_3_TAB);
			ptxtWriter.Write ("BaseAdo{0}.InsertUpdate (ref pobjI);", pobjObject.Name);
			
			ptxtWriter.WriteLine (TextHelper.NL_2_TAB_CC);
		}
		
		
		private static void GenerateInsertArray (ref TextWriter ptxtWriter, XmlObject pobjObject, XmlMember pobjMember, XmlObject pobjExtRefObject)
		{
			ptxtWriter.Write (TextHelper.NL_2_TAB);
			ptxtWriter.Write ("public static void Insert_ArrayOf{0} ({1} pobjA, {2} pobjB)", 
				pobjMember.Name, pobjObject.Name, pobjExtRefObject.Name);
			ptxtWriter.Write (TextHelper.NL_2_TAB_CO);
				
			ptxtWriter.Write ("{0}.Validator.FilledID (pobjA.ID);", pobjObject.Name);
			ptxtWriter.Write ("{0}.Validator.FilledID (pobjB.ID);", pobjExtRefObject.Name);
				
			ptxtWriter.Write (TextHelper.NL_3_TAB);
			ptxtWriter.Write ("BaseAdo{0}.Insert_ArrayOf{1} (pobjA, pobjB);", pobjObject.Name, pobjMember.Name);
				
			ptxtWriter.WriteLine (TextHelper.NL_2_TAB_CC);
		}
		
		
		private static void GenerateDeleteArrayByRef (ref TextWriter ptxtWriter, XmlObject pobjObject, XmlMember pobjMember, XmlObject pobjExtRefObject)
		{
			ptxtWriter.Write (TextHelper.NL_2_TAB);
			ptxtWriter.Write ("public static void Delete_ArrayOf{0}By{1} ({1} pobjI)", pobjMember.Name, pobjExtRefObject.Name);
			ptxtWriter.Write (TextHelper.NL_2_TAB_CO);
			
			ptxtWriter.Write ("{0}.Validator.FilledID (pobjI.ID);", pobjExtRefObject.Name);
			
			ptxtWriter.Write (TextHelper.NL_3_TAB);
			ptxtWriter.Write ("BaseAdo{0}.Delete_ArrayOf{1}By{2} (pobjI);", pobjObject.Name, pobjMember.Name, pobjExtRefObject.Name);
			
			ptxtWriter.WriteLine (TextHelper.NL_2_TAB_CC);
		}
		
		
		private static void GenerateDeleteArrayBySelf (ref TextWriter ptxtWriter, XmlObject pobjObject, XmlMember pobjMember, XmlObject pobjExtRefObject)
		{
			ptxtWriter.Write (TextHelper.NL_2_TAB);
			ptxtWriter.Write ("public static void Delete_ArrayOf{0}By{1} ({1} pobjI)", pobjMember.Name, pobjObject.Name);
			ptxtWriter.Write (TextHelper.NL_2_TAB_CO);
			
			ptxtWriter.Write ("{0}.Validator.FilledID (pobjI.ID);", pobjObject.Name);
			
			ptxtWriter.Write (TextHelper.NL_3_TAB);
			ptxtWriter.Write ("BaseAdo{0}.Delete_ArrayOf{1}By{0} (pobjI);", pobjObject.Name, pobjMember.Name);
			
			ptxtWriter.WriteLine (TextHelper.NL_2_TAB_CC);
		}
		
		#endregion
	}
}